﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RecipesManager.RecipesImporter
{
    //Classe per validare i dati della ImportedRecipe
    class InputValidator
    {
        #region PrivateData
        private static HashSet<string> measuringUnits;
        private static int MAX_STRING_LENGTH = 200;
        private static int MIN_HOURS = 0;
        private static int MAX_HOURS = 72;
        private static int MIN_MINUTES = 0;
        private static int MAX_MINUTES = 55;
        private static int MIN_SERVINGS = 0;
        private static int MAX_SERVINGS = 50;
        private static int MIN_QUANTITY = 1;
        private static int MAX_QUANTITY = 10000;
        private static int EMPTY_VALUE = -10000;

        static InputValidator()
        {
          measuringUnits = new HashSet<string>();
          measuringUnits.Add("stati uniti");
          measuringUnits.Add("metrico");
          measuringUnits.Add("britannico");
        }
        #endregion

        public static bool validateRecipe(ImportedRecipe recipe)
        {
            correctMeasuringUnit(recipe);

            return validateName(recipe.Name) && validateOriginalSource(recipe.OriginalSource) &&
                   validatePreparationHours(recipe.PreparationHours) && validatePreparationMinutes(recipe.PreparationMinutes) &&
                   validateServings(recipe.Servings) && validateMeasuringUnit(recipe.MeasuringUnit) &&
                   validateIngredients(recipe.Ingredients) && validateSteps(recipe.Steps) &&
                   validateTrials(recipe.Trials);
        }

        #region validateRecipeSupportMethods
        private static bool validateName(string s)
        {
            return !(s.Equals("")) && validateString(s);
        }

        private static bool validateOriginalSource(string s)
        {
            return validateString(s);
        }

        private static bool validatePreparationHours(int i)
        {
            return i == EMPTY_VALUE || i >= MIN_HOURS && i <= MAX_HOURS;
        }

        private static bool validatePreparationMinutes(int i)
        {
            return i == EMPTY_VALUE || i >= MIN_MINUTES && i <= MAX_MINUTES;
        }

        private static bool validateServings(int i)
        {
            return i == EMPTY_VALUE || i >= MIN_SERVINGS && i <= MAX_SERVINGS;
        }

        private static bool validateMeasuringUnit(string s)
        {
            return s.Equals("") || isMeasuringUnitLine(s);
        }

        private static bool validateIngredients(List<ImportedIngredient> ingredients)
        {
            if (ingredients.Count == 0)
                return true;

            foreach (ImportedIngredient i in ingredients)
            {
                if (!validateIngredient(i))
                    return false;
            }
            return true;
        }

        private static bool validateIngredient(ImportedIngredient i)
        {
            return validateIngredientName(i.Name) && validateIngredientQuantity(i.Quantity) && validateIngredientNote(i.Note);
        }

        private static bool validateIngredientName(string s)
        {
            return validateString(s);
        }

        private static bool validateIngredientQuantity(string s)
        {
            string[] s1 = s.Split(' ');
            if (s1.Length < 2)
              return false;

            int quantity = Convert.ToInt32(s1[0]);

            return validateString(s1[1]) && quantity >= MIN_QUANTITY && quantity <= MAX_QUANTITY;
        }

        private static bool validateIngredientNote(string s)
        {
            return validateString(s);
        }

        private static bool validateSteps(List<string> steps)
        {
            return true;
        }

        private static bool validateTrials(List<string> trials)
        {
            return true;
        }

        private static bool validateString(string s)
        {
            return s.Length <= MAX_STRING_LENGTH;
        }

        private static bool isMeasuringUnitLine(string s)
        {
            foreach (var m in measuringUnits)
            {
              if (s.Trim().ToLower().Equals(m))
                return true;
            }
            return false;
        }

        private static void correctMeasuringUnit(ImportedRecipe recipe)
        {
          if(!isMeasuringUnitLine(recipe.MeasuringUnit))
            recipe.MeasuringUnit = "";
        }
        #endregion
    }
    
}
